package com.gksc.video.manager;

import com.gksc.video.config.PushConfig;
import com.gksc.video.constant.BusinessConstant;
import com.gksc.video.constant.CacheConstant;
import com.gksc.video.data.DeviceInfo;
import com.gksc.video.enums.StreamType;
import lombok.extern.slf4j.Slf4j;
import org.bytedeco.ffmpeg.global.avutil;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FFmpegLogCallback;
import org.springframework.util.ObjectUtils;

/**
 * @className: VideoPushThread
 * @description: rtsp推视频流线程
 * @author: Liao.yx
 * @email: 1229053515@qq.com
 * @create: 2021年05月14日 16时29分
 * @copyRight: 2020 liaoyongxiang All rights reserved.
 **/
@Slf4j
public class StreamPushThread extends BasePushThread implements Runnable {
    /**
     * 录像设备信息
     */
    private DeviceInfo cameraInfo;
    /**
     * 采集器
     */
    private FFmpegFrameGrabber grabber;
    /**
     * 推流配置信息
     */
    private PushConfig pushConfig;

    public StreamPushThread(DeviceInfo cameraInfo, PushConfig pushConfig) {
        this.cameraInfo = cameraInfo;
        this.pushConfig = pushConfig;
    }

    @Override
    public void run() {
        try {
            CacheConstant.STREATMAP.put(cameraInfo.getToken(), cameraInfo);
            CacheConstant.JOBMAP.put(cameraInfo.getToken(), this);
            avutil.av_log_set_level(avutil.AV_LOG_INFO);
            FFmpegLogCallback.set();
            Integer probeSize = StreamType.MAIN.getType() == cameraInfo.getStream() ? pushConfig.getMainCode() : pushConfig.getSubCode();
            grabber = new FFmpegFrameGrabber(cameraInfo.getDealUrl());
            grabber.setOption(BusinessConstant.GrabberOption.BUFFER_SIZE, "1024000");
            grabber.setOption(BusinessConstant.GrabberOption.MAX_DELAY, "500000");
            grabber.setOption(BusinessConstant.GrabberOption.TIMEOUT, "20000000");
            grabber.setOption(BusinessConstant.GrabberOption.RTSP_TRANS, "tcp");
            grabber.start();
            if (!ObjectUtils.isEmpty(probeSize)) {
                grabber.setOption(BusinessConstant.GrabberOption.PROBE_SIZE, probeSize + "");
            }
            super.push(grabber, cameraInfo);
        } catch (Exception e) {
            log.error("推流失败，设备信息：{}，异常原因{}", cameraInfo.toString(), e);
            e.printStackTrace();
        } finally {
            release();
            CacheConstant.STREATMAP.remove(cameraInfo.getToken());
            CacheConstant.JOBMAP.remove(cameraInfo.getToken());
            log.info("结束推流 设备信息：{}", cameraInfo.toString());
        }
    }

    /**
     * @return void
     * @Title: release
     * @Description:资源释放
     **/
    public void release() {
        log.info("{}释放资源", Thread.currentThread().getName());
        try {
            if (grabber != null) {
                grabber.stop();
                grabber.close();
            }
            super.release();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 线程终止退出
     */
    public void cancel() {
        super.cancel();
    }
}
